package com.apes.framework.plugin.soe.store.database.service;

import com.apes.framework.api.DomainService;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.plugin.event.Listener;
import com.apes.framework.plugin.outbox.OutboxSubscriber;
import com.apes.framework.plugin.outbox.OutboxSubscriberManager;
import com.apes.framework.plugin.soe.metadata.Scene;
import com.apes.framework.plugin.soe.metadata.SceneRole;
import com.apes.framework.plugin.soe.store.database.repository.SceneRepository;
import com.apes.framework.util.JpaUtil;
import com.apes.framework.util.MapUtil;
import com.apes.framework.util.ReflectUtil;
import org.hibernate.query.internal.NativeQueryImpl;
import org.hibernate.transform.Transformers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.persistence.EntityManager;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Service("sceneService")
public class SceneService extends DomainService {

    @Autowired
    SceneRepository sceneRepository;

    public Scene save(SimpleRequest simpleRequest) {
        Scene scene = simpleRequest.getO(Scene.class);
        if(scene.getSceneRoles().stream().filter(sceneRole -> sceneRole.isInitiate()).count() != 1){
            throw new RuntimeException("一个场景有且只能有一个发起凭证");
        }
        return sceneRepository.saveAndFlush(scene);
    }

    @Listener(topic = "event:scene.check")
    public void onCheck(SimpleRequest simpleRequest) {
        Scene scene = simpleRequest.getO(Scene.class);
        //更新合法标记
        scene.setRightful(scene.check());
        sceneRepository.saveAndFlush(scene);
    }

    public Scene findById(String sceneId) {
        return sceneRepository.findOne(sceneId);
    }

    public Map rerun(SimpleRequest simpleRequest) {
        String entityName = simpleRequest.get("entityName");
        String id = simpleRequest.get("id");
        Class clazz = ReflectUtil.getClass(entityName);
        Object entity = JpaUtil.getRepository(entityName).findOne(JpaUtil.getId(clazz.getSimpleName(), id));
        invoke("soe.consume", entity);
        return MapUtil.mapper("id", "成功！");
    }

    @Autowired
    private EntityManager entityManager;

    @Listener(topic = "outbox.subscriber.init")
    public List<OutboxSubscriber> getOutboxSubscribers(SimpleRequest request) {
        List<OutboxSubscriber> outboxSubscribers = new ArrayList<>();
        sceneRepository.findAll("select distinct business_type_id from soe_scene_role").stream().forEach(m -> {
            String classSimpleName = (String) m;
            String eventType = "S";
            OutboxSubscriber outboxSubscriber = createOutboxSubscriber(classSimpleName, eventType);
            if (outboxSubscriber == null) return;
            if (outboxSubscriber != null) outboxSubscribers.add(outboxSubscriber);
        });
        OutboxSubscriber outboxSubscriber = outboxSubscriberManager.createOutboxSubscriber(SceneRole.class, "soe.subscriber.add", "新增SceneRole触发事件订阅", "S", "soe.scene.addOutboxSubscriberBySceneRole");
        outboxSubscribers.add(outboxSubscriber);
        outboxSubscriber = outboxSubscriberManager.createOutboxSubscriber(SceneRole.class, "soe.subscriber.delete", "删除SceneRole触发事件订阅", "D", "soe.scene.removeOutboxSubscriberBySceneRole");
        outboxSubscribers.add(outboxSubscriber);
        return outboxSubscribers;
    }

    @Autowired
    private OutboxSubscriberManager outboxSubscriberManager;

    public void addOutboxSubscriberBySceneRole(SimpleRequest request) {
        SceneRole sceneRole = request.getO(SceneRole.class);
        String classSimpleName = sceneRole.getBusinessType().getId();
        String eventType = "S";
        OutboxSubscriber outboxSubscriber = createOutboxSubscriber(classSimpleName, eventType);
        if (outboxSubscriber == null) return;
        outboxSubscriberManager.addOutboxSubscriber(outboxSubscriber);
    }

    public void removeOutboxSubscriberBySceneRole(SimpleRequest request) {
        SceneRole sceneRole = request.getO(SceneRole.class);
        String classSimpleName = sceneRole.getBusinessType().getId();
        String eventType = "D";
        OutboxSubscriber outboxSubscriber = createOutboxSubscriber(classSimpleName, eventType);
        if (outboxSubscriber == null) return;
        outboxSubscriberManager.removeOutboxSubscriber(outboxSubscriber);
    }

    private OutboxSubscriber createOutboxSubscriber(String classSimpleName, String eventType) {
        Class clazz = JpaUtil.getDomainClass(classSimpleName);
        if (clazz == null) return null;
        String outboxSubscriberId = "soe.consume." + classSimpleName;
        String outboxSubscriberName = "场景流事件拦截：" + classSimpleName;
        OutboxSubscriber outboxSubscriber = outboxSubscriberManager.createOutboxSubscriber(clazz, outboxSubscriberId, outboxSubscriberName, eventType, "soe.consume");
        return outboxSubscriber;
    }
}
